﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Validation;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Web;
using TY.UC.Common;

namespace TY.DM.Dal.EF
{
    /// <summary>
    /// 通用方法
    /// </summary>
    /// <typeparam name="TEfEntity">EF自动生成的实体类</typeparam>
    /// <typeparam name="TModel">Model</typeparam>
    /// <typeparam name="TEntities">数据库Entities</typeparam>
    public abstract class BaseService<TModel, TEfEntity, TEntities>
        where TModel : class, new()
        where TEfEntity : class, new()
        where TEntities : DbContext, new()
    {

        protected readonly TEntities EfContext;
          /// <summary>Default constructor.
        /// </summary>
        protected BaseService()
        {
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="key">数据库上下文名称</param>
        protected BaseService(string key)
            : this()
        {
            if (HttpContext.Current != null)
            {
                var dbContext = HttpContext.Current.Items[key] as TEntities;
                if (dbContext != null)
                    EfContext = dbContext;
                else
                {
                    dbContext = new TEntities();
                    HttpContext.Current.Items[key] = dbContext;
                    EfContext = dbContext;
                }
            }
        }

        #region 操作EF实体
 
        /// <summary>
        /// 分页方法
        /// </summary>
        /// <typeparam name="TS">排序的约束</typeparam>
        /// <param name="pageIndex">当前页码</param>
        /// <param name="pageSize">每页显示记录数</param>
        /// <param name="totalCount">总条数</param>
        /// <param name="whereLambda">过滤条件</param>
        /// <param name="orderbyLambda">排序条件</param>
        /// <param name="isAsc">排序方式</param>
        /// <returns></returns>
        public IQueryable<TEfEntity> LoadPageEntities<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<TEfEntity, bool>> whereLambda, Expression<Func<TEfEntity, TS>> orderbyLambda, bool isAsc)
        {
            var temp = EfContext.Set<TEfEntity>().Where<TEfEntity>(whereLambda);
            totalCount = temp.Count();
            temp = isAsc ? temp.OrderBy(orderbyLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize) : temp.OrderByDescending(orderbyLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize);
            return temp;

        }

        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="tEfEntity">Ef单个实体</param>
        /// <returns>成功/失败</returns>
        public bool AddEntity(TEfEntity tEfEntity)
        {
            try
            {
                if (tEfEntity == null) return false;
                EfContext.Entry(tEfEntity).State = EntityState.Added;
                return EfContext.SaveChanges() > 0;
            }
            catch (DbEntityValidationException ex)
            {
                LogHelper.WriteLog("DM.Dal", "BaseService-AddEntity,入参:", tEfEntity, ex);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("DM.Dal", "BaseService-AddEntity,入参:" ,tEfEntity, ex);
            }
            return false;
        }

        /// <summary>
        /// 删除数据
        /// </summary>
        /// <param name="tEfEntity">EF实体</param>
        /// <returns>成功/失败</returns>
        public bool DeleteEntity(TEfEntity tEfEntity)
        {
            try
            {
                if (tEfEntity == null) return false;
                EfContext.Entry(tEfEntity).State = EntityState.Deleted;
                return EfContext.SaveChanges() > 0;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("DM.Dal", "BaseService-DeleteEntity,入参:tEfEntity = ",tEfEntity, ex);
            }
            return false;
        }
 
        /// <summary>
        /// 根据条件删除数据
        /// </summary>
        /// <param name="where">删除条件</param>
        /// <returns></returns>
        public bool DeleteEntity(Expression<Func<TEfEntity, bool>> where)
        {
            try
            {
                var tEfEntity = EfContext.Set<TEfEntity>().Where(where);
                if (tEfEntity.Any())
                {
                    foreach (var efEntity in tEfEntity)
                    {
                        EfContext.Set<TEfEntity>().Remove(efEntity);
                    }
                    return EfContext.SaveChanges() > 0;
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("DM.Dal", "BaseService-GetFirstOrDefaultEfEntity,入参:where = " , where, ex);
            }
            return false;
        }

        /// <summary>
        /// 修改数据
        /// </summary>
        /// <param name="tEfEntity">Ef实体</param>
        /// <returns>成功/失败</returns>
        public bool UpdateEntity(TEfEntity tEfEntity)
        {
            try
            {
                EfContext.Set<TEfEntity>().Attach(tEfEntity);
                EfContext.Entry(tEfEntity).State = EntityState.Modified;
                return EfContext.SaveChanges() > 0;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("DM.Dal", "BaseService-Update,入参：tEfEntity = ",tEfEntity, ex);
            }
            return false;
        }
        /// <summary>
        /// 指定字段修改
        /// </summary>
        /// <param name="where"></param>
        /// <param name="dic"></param>
        public bool Update(Expression<Func<TEfEntity, bool>> where, Dictionary<string, object> dic)
        {
            try
            {
                IEnumerable<TEfEntity> result = EfContext.Set<TEfEntity>().Where(where).ToList();
                if (!result.Any()) return false;
                var type = typeof(TEfEntity);
                var propertyList = type.GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList();
                //遍历结果集
                foreach (var entity in result)
                {
                    //bool isUpdate = false;
                    foreach (var item in dic)
                    {
                        var propertyName =
                            propertyList.Where(
                                p => string.Compare(p.Name, item.Key, StringComparison.OrdinalIgnoreCase) == 0)
                                .Select(p => p.Name)
                                .FirstOrDefault();
                        if (string.IsNullOrEmpty(propertyName)) continue;
                        EfContext.Entry(entity).Property(propertyName).CurrentValue = dic[propertyName];
                        EfContext.Entry(entity).Property(propertyName).IsModified = true;
                    }
                }
                return EfContext.SaveChanges() > 0;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("DM.Dal", "BaseService-Update,入参：dic = " ,dic, ex);
            }
            return false;
        }
        #endregion


        #region 反射动态合并Model与EFModel
        /// <summary>
        /// 反射动态合并Model(将Model为null对应EF不为null的字段值替换)
        /// </summary>
        /// <param name="model"></param>
        /// <param name="ef"></param>
        /// <returns></returns>
        public TModel DynamicReplaceValue(TModel model, TEfEntity ef)
        {
            var mtype = model.GetType();//获取指定名称的类型
            var etype = ef.GetType();//获取指定名称的类型
            var mfield = mtype.GetProperties(); //获取指定对象的所有公共属性
            var efield = etype.GetProperties(); //获取指定对象的所有公共属性
            //遍历Model
            foreach (var m in mfield)
            {
                //遍历EF实体,将EF值赋值给Model(EF有值Model没值的会将EF值赋给Model)
                foreach (var e in efield)
                {
                    if (m.Name == e.Name && e.GetValue(ef, null) != null && m.GetValue(model, null) == null)
                    {
                        m.SetValue(model, e.GetValue(ef, null), null); //给对象赋值
                    }
                }
            }
            return model;
        }
        /// <summary>
        /// 反射动态合并EFModel(将EFModel为null对应Model不为null的字段值替换/EFModel与Model对应字段值不一样的替换)
        /// </summary>
        /// <param name="ef"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        public TEfEntity DynamicReplaceValue(TEfEntity ef, TModel model)
        {
            var mtype = model.GetType();//获取指定名称的类型
            var etype = ef.GetType();//获取指定名称的类型
            var mfield = mtype.GetProperties(); //获取指定对象的所有公共属性
            var efield = etype.GetProperties(); //获取指定对象的所有公共属性
            //遍历EF
            foreach (var e in efield)
            {
                //遍历Model实体,将Model值赋值给EF(Model有值EF没值的会将Model值赋给EF)
                foreach (var m in mfield)
                {
                    if (e.Name == m.Name)
                    {
                        if (m.GetValue(model, null) != null)
                        {
                            //给字段赋值
                            e.SetValue(ef, m.GetValue(model, null), null);
                        }
                    }
                }
            }
            return ef;
        }
        #endregion
    }
}
